using System;
using System.Collections;
using System.Collections.Generic;
using System.Data;
using Oracle.ManagedDataAccess.Client;
using OracleInternal.Common;
using OracleInternal.I18N;

namespace OracleInternal.ServiceObjects
{
	internal class NotificationDetails
	{
		private const byte TBL_OPCODE_ALLROWS = 1;

		private const byte TBL_OPCODE_ALLOPS = 0;

		private const byte TBL_OPCODE_INSERT = 2;

		private const byte TBL_OPCODE_UPDATE = 4;

		private const byte TBL_OPCODE_DELETE = 8;

		private const byte TBL_OPCODE_ALTER = 16;

		private const byte TBL_OPCODE_DROP = 32;

		private const byte TBL_OPCODE_UNKNOWN = 64;

		private byte[] m_notificationInfoBuffer;

		private short m_csId;

		internal Conv m_dbCharSetConv;

		internal bool m_bCanUseSecureCQN;

		internal OracleNotificationType m_type;

		internal OracleNotificationSource m_source;

		internal OracleNotificationInfo m_info;

		internal string[] m_resources;

		internal DataTable m_details;

		internal ByteBuffer m_byteBuffer;

		private ArrayList resourceNamesList = new ArrayList();

		internal List<long> m_queryIdList = new List<long>();

		internal int m_regIdFromServer;

		internal NotificationDetails(short csId, Conv dbCharSetConv, int regIdFromServer, byte[] notifInfo, bool bCanUseSecureCQN)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ctor);
			}
			try
			{
				m_notificationInfoBuffer = notifInfo;
				m_csId = csId;
				m_dbCharSetConv = dbCharSetConv;
				m_regIdFromServer = regIdFromServer;
				m_bCanUseSecureCQN = bCanUseSecureCQN;
				m_type = OracleNotificationType.Change;
				m_source = OracleNotificationSource.Data;
				m_info = OracleNotificationInfo.Update;
				m_resources = new string[0];
				m_details = new DataTable();
				m_details.Columns.Add("ResourceName", typeof(string));
				m_details.Columns.Add("Info", typeof(OracleNotificationInfo));
				m_details.Columns.Add("Rowid", typeof(string));
				m_details.Columns.Add("QueryId", typeof(long));
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ctor, ex);
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ctor);
				}
			}
		}

		internal void ParseNotificationInfo()
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ParseNotificationInfo);
			}
			try
			{
				int offset = -1;
				if (m_notificationInfoBuffer == null || m_notificationInfoBuffer.Length == 0)
				{
					return;
				}
				m_byteBuffer = new ByteBuffer(m_notificationInfoBuffer.Length);
				m_byteBuffer.m_byteBuffer = m_notificationInfoBuffer;
				m_byteBuffer.Limit = m_notificationInfoBuffer.Length;
				if (!m_bCanUseSecureCQN)
				{
					m_byteBuffer.GetByte();
					int @int = m_byteBuffer.GetInt();
					byte[] userBuff = null;
					m_byteBuffer.GetBufferRef(out userBuff, out offset, @int);
					string text = Conv.GetInstance(871).ConvertBytesToString(userBuff, offset, @int);
					text = text.Trim("CHNF".ToCharArray());
					m_regIdFromServer = int.Parse(text);
					m_byteBuffer.GetByte();
					int int2 = m_byteBuffer.GetInt();
					byte[] userBuff2 = null;
					m_byteBuffer.GetBufferRef(out userBuff2, out offset, int2);
					m_byteBuffer.GetByte();
					m_byteBuffer.GetInt();
				}
				if (m_byteBuffer.HasRemaining)
				{
					m_byteBuffer.GetShort();
					m_byteBuffer.GetInt();
					SetNotificationTypeSourceInfo(m_byteBuffer.GetInt());
					if (m_source == OracleNotificationSource.Data)
					{
						int @short = m_byteBuffer.GetShort();
						byte[] userBuff3 = null;
						m_byteBuffer.GetBufferRef(out userBuff3, out offset, @short);
						Conv.GetInstance(871).ConvertBytesToString(userBuff3, offset, @short);
						m_byteBuffer.GetLong();
						m_byteBuffer.GetInt();
						m_byteBuffer.GetShort();
						if (m_type == OracleNotificationType.Query)
						{
							short short2 = m_byteBuffer.GetShort();
							for (int i = 0; i < short2; i++)
							{
								ReadQueryInfo(resourceNamesList);
							}
						}
						else if (m_type == OracleNotificationType.Change)
						{
							int short3 = m_byteBuffer.GetShort();
							for (int j = 0; j < short3; j++)
							{
								ReadTableInfo(0L, resourceNamesList);
							}
						}
						m_resources = (string[])resourceNamesList.ToArray(typeof(string));
						if (resourceNamesList.Count > 0)
						{
							resourceNamesList.Clear();
						}
						if (m_details.Rows.Count > 0)
						{
							m_info = (OracleNotificationInfo)m_details.Rows[0][1];
						}
						else
						{
							m_info = OracleNotificationInfo.Error;
						}
					}
				}
				m_byteBuffer = null;
				m_notificationInfoBuffer = null;
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ParseNotificationInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ParseNotificationInfo);
				}
			}
		}

		private void ReadQueryInfo(ArrayList resourceNamesList)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadQueryInfo);
			}
			try
			{
				long num = m_byteBuffer.GetInt();
				long num2 = m_byteBuffer.GetInt();
				long num3 = num | (num2 << 32);
				if (!m_queryIdList.Contains(num3))
				{
					m_queryIdList.Add(num3);
				}
				m_byteBuffer.GetInt();
				int @short = m_byteBuffer.GetShort();
				for (int i = 0; i < @short; i++)
				{
					ReadTableInfo(num3, resourceNamesList);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadQueryInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadQueryInfo);
				}
			}
		}

		internal void ReadTableInfo(long queryId, ArrayList resourceNamesList)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadTableInfo);
			}
			try
			{
				int @int = m_byteBuffer.GetInt();
				int @short = m_byteBuffer.GetShort();
				byte[] userBuff = null;
				int offset = -1;
				m_byteBuffer.GetBufferRef(out userBuff, out offset, @short);
				string text = "";
				text = ((m_dbCharSetConv == null) ? Conv.GetInstance(m_csId).ConvertBytesToString(userBuff, offset, @short) : m_dbCharSetConv.ConvertBytesToString(userBuff, offset, @short));
				resourceNamesList.Add(text);
				m_byteBuffer.GetInt();
				int num = 0;
				if ((@int & 1) == 0)
				{
					num = m_byteBuffer.GetShort();
				}
				if (num == 0)
				{
					if (((uint)@int & 0x10u) != 0)
					{
						m_source = OracleNotificationSource.Object;
						AddRowDetail(text, OracleNotificationInfo.Alter, null, queryId);
					}
					if (((uint)@int & 0x20u) != 0)
					{
						m_source = OracleNotificationSource.Object;
						AddRowDetail(text, OracleNotificationInfo.Drop, null, queryId);
					}
					if (((uint)@int & 4u) != 0)
					{
						AddRowDetail(text, OracleNotificationInfo.Update, null, queryId);
					}
					if (((uint)@int & 2u) != 0)
					{
						AddRowDetail(text, OracleNotificationInfo.Insert, null, queryId);
					}
					if (((uint)@int & 8u) != 0)
					{
						AddRowDetail(text, OracleNotificationInfo.Delete, null, queryId);
					}
				}
				else
				{
					for (int i = 0; i < num; i++)
					{
						ReadRowInfo(queryId, text);
					}
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadTableInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadTableInfo);
				}
			}
		}

		internal void ReadRowInfo(long queryId, string tableName)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadRowInfo);
			}
			try
			{
				int @int = m_byteBuffer.GetInt();
				int @short = m_byteBuffer.GetShort();
				byte[] userBuff = null;
				int offset = -1;
				m_byteBuffer.GetBufferRef(out userBuff, out offset, @short);
				string rowid = Conv.GetInstance(871).ConvertBytesToString(userBuff, offset, @short);
				if (((uint)@int & 0x10u) != 0)
				{
					m_source = OracleNotificationSource.Object;
					AddRowDetail(tableName, OracleNotificationInfo.Alter, null, queryId);
				}
				if (((uint)@int & 0x20u) != 0)
				{
					m_source = OracleNotificationSource.Object;
					AddRowDetail(tableName, OracleNotificationInfo.Drop, null, queryId);
				}
				if (((uint)@int & 2u) != 0)
				{
					AddRowDetail(tableName, OracleNotificationInfo.Insert, rowid, queryId);
				}
				if (((uint)@int & 8u) != 0)
				{
					AddRowDetail(tableName, OracleNotificationInfo.Delete, rowid, queryId);
				}
				if (((uint)@int & 4u) != 0)
				{
					AddRowDetail(tableName, OracleNotificationInfo.Update, rowid, queryId);
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadRowInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.ReadRowInfo);
				}
			}
		}

		internal void AddRowDetail(string name, OracleNotificationInfo info, string rowid, long queryid)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.AddRowDetail);
			}
			try
			{
				DataRow dataRow = m_details.NewRow();
				dataRow[0] = name;
				dataRow[1] = info;
				dataRow[2] = rowid;
				dataRow[3] = queryid;
				m_details.Rows.Add(dataRow);
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.AddRowDetail, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.AddRowDetail);
				}
			}
		}

		internal void SetNotificationTypeSourceInfo(int notifId)
		{
			if (ProviderConfig.m_bTraceLevelPrivate)
			{
				Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262400, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.SetNotificationTypeSourceInfo);
			}
			try
			{
				switch (notifId)
				{
				case 1:
					m_type = OracleNotificationType.Change;
					m_source = OracleNotificationSource.Database;
					m_info = OracleNotificationInfo.Startup;
					break;
				case 2:
					m_type = OracleNotificationType.Change;
					m_source = OracleNotificationSource.Database;
					m_info = OracleNotificationInfo.Shutdown;
					break;
				case 3:
					m_type = OracleNotificationType.Change;
					m_source = OracleNotificationSource.Database;
					m_info = OracleNotificationInfo.Shutdown_any;
					break;
				case 4:
					m_type = OracleNotificationType.Change;
					m_source = OracleNotificationSource.Database;
					m_info = OracleNotificationInfo.Drop;
					break;
				case 5:
					m_type = OracleNotificationType.Subscribe;
					m_source = OracleNotificationSource.Subscription;
					m_info = OracleNotificationInfo.End;
					break;
				case 6:
					m_type = OracleNotificationType.Change;
					m_source = OracleNotificationSource.Data;
					break;
				case 7:
					m_type = OracleNotificationType.Query;
					m_source = OracleNotificationSource.Data;
					break;
				default:
					throw new NotSupportedException("Unsupported DB Change Event...");
				}
			}
			catch (Exception ex)
			{
				OracleException.HandleError(OracleTraceLevel.Private, (OracleTraceTag)268697600, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.SetNotificationTypeSourceInfo, ex);
				throw;
			}
			finally
			{
				if (ProviderConfig.m_bTraceLevelPrivate)
				{
					Trace.Write(OracleTraceLevel.Private, (OracleTraceTag)262656, OracleTraceClassName.NotificationDetails, OracleTraceFuncName.SetNotificationTypeSourceInfo);
				}
			}
		}
	}
}
